/*
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package utopiaintelpackage.sot;

import java.util.Date;

import main.CommonMethods;
import main.Main;

import org.apache.log4j.Logger;

import tools.StringTools;
import tools.UtopiaTime;
import exceptions.IntelParsingException;
import exceptions.UtoDateException;

/**
 * This class parses SoT's
 * 
 * 
 */
public class SoTParser {
   private final String persregex = CommonMethods.getPersonalitiesRegex();
   private final String titlesregex = CommonMethods.getTitlesRegex();
   private final String racesregex = CommonMethods.getRacesRegex(false);

   public void parseFormattedSoT(final String input, final SoT sot) throws IntelParsingException {
	  String in = input;
	  if (in.matches("The Province of .*\\([0-9]{1,2}(:)[0-9]{1,2}\\)")) {
		 in = in.replace("The Province of ", "");

		 String prov = in.substring(0, in.indexOf('(')).trim();
		 String kd = (in.substring(in.indexOf('('), in.indexOf(')')) + ")").trim();
		 sot.setName(prov);
		 sot.setKdloc(kd);
	  } else if (in.matches("Utopian Date: (January|February|March"
			+ "|April|May|June|July) (?:(?:[0-1][0-9])|(?:[2][0-4])|(?:[1-9]))(th, YR|rd, YR|st, YR|nd, YR)"
			+ "[0-9]{1,2} \\([0-9]{1,}.*")) {
		 in = in.replaceFirst("Utopian Date: ", "");
		 String utodate = in.substring(0, in.indexOf('(')).trim();
		 int intoHour = Integer.parseInt(in.substring(in.indexOf('(') + 1).replaceAll("[^0-9]", ""));
		 Double minutes = intoHour / 100.0 * Main.getBotSettings().getTickLength();
		 UtopiaTime ut;
		 try {
			ut = new UtopiaTime(utodate);
			Date date = new Date(ut.getTime() + minutes.longValue() * Main.getBotSettings().getTickLength() * 1000);
			sot.setUpdated(date);
		 } catch (final UtoDateException e) {
			Logger.getLogger("Error").error("", e);
			throw new IntelParsingException();
		 }
	  } else if (in.matches("Ruler Name: The " + persregex + " " + titlesregex + " .*")) {
		 String title = in.replaceAll("Ruler Name: The " + persregex + " ", "");
		 String rulerName = title.replaceFirst(titlesregex, "").trim();
		 title = title.replace(rulerName, "").trim();
		 sot.setRulerName(rulerName);
		 sot.setTitle(title);
	  } else if (in.matches("Ruler Name: The " + persregex + " .*")) {
		 String rulerName = in.replaceAll("Ruler Name: The " + persregex + " ", "");
		 sot.setRulerName(rulerName);
		 sot.setTitle("Peasant");
	  } else if (in.matches("Ruler Name: " + titlesregex + " .* the " + persregex)) {
		 String rulerName = in.replaceAll("Ruler Name: " + titlesregex + " ", "");
		 rulerName = rulerName.replaceAll(" the " + persregex, "");
		 String title = in.replace("Ruler Name: ", "");
		 title = title.replaceAll(rulerName + ".*", "");
		 sot.setRulerName(rulerName);
		 sot.setTitle(title);
	  } else if (in.matches("Ruler Name: .* the " + persregex)) {
		 String rulerName = in.replaceAll("Ruler Name: ", "");
		 rulerName = rulerName.replaceAll(" the " + persregex, "");
		 sot.setRulerName(rulerName);
		 sot.setTitle("Peasant");
	  } else if (in.matches("Personality & Race: The " + persregex + ", " + racesregex)) {
		 in = in.replace("Personality & Race: The ", "");
		 String pers = in.substring(0, in.indexOf(',')).trim();
		 String race = in.substring(in.indexOf(',') + 1).trim();
		 sot.setPersonality(pers);
		 sot.setRace(race);
	  } else if (in.matches("Land: [0-9,]{1,} Acres.*")) {
		 in = in.replace("Land: ", "");
		 in = in.substring(0, in.indexOf(" Acres"));
		 String land = in.replace(",", "").trim();
		 sot.setLand(Integer.parseInt(land));
	  } else if (in.matches("Money: [0-9,]{1,}gc.*daily income.*")) {
		 in = in.replace("Money: ", "");
		 in = in.substring(0, in.indexOf("gc"));
		 String money = in.replace(",", "").trim();
		 sot.setMoney(Integer.parseInt(money));
	  } else if (in.matches("Food: [0-9,]{1,} bushels.*")) {
		 in = in.replace("Food: ", "");
		 in = in.substring(0, in.indexOf(" bushels"));
		 String food = in.replace(",", "").trim();
		 sot.setFood(Integer.parseInt(food));
	  } else if (in.matches("Runes: [0-9,]{1,} runes.*")) {
		 in = in.replace("Runes: ", "");
		 in = in.substring(0, in.indexOf(" runes"));
		 String runes = in.replace(",", "").trim();
		 sot.setRunes(Integer.parseInt(runes));
	  } else if (in.matches("Peasants: [0-9,]{1,} \\([0-9]{1,}.*")) {
		 in = in.replace("Peasants: ", "");
		 String peasants = in.substring(0, in.indexOf('('));
		 String be = in.substring(in.indexOf('('));
		 be = be.replaceAll("[^0-9]", "");
		 peasants = peasants.replace(",", "").trim();
		 sot.setPeasants(Integer.parseInt(peasants));
		 sot.setBe(be);
	  } else if (in.matches("Trade Balance: [-0-9,]{1,}gc.*")) {
		 in = in.replace("Trade Balance: ", "");
		 String tradeBalance = in.substring(0, in.indexOf("gc"));
		 sot.setTradeBalance(Integer.parseInt(tradeBalance.replace(",", "").trim()));
	  } else if (in.matches("Total Networth: [0-9,]{1,}gc.*")) {
		 in = in.replace("Total Networth: ", "");
		 if (in.indexOf(' ') != -1) {
			in = in.substring(0, in.indexOf(' '));
		 }
		 String nw = in.replace("gc", "").replace(",", "").trim();
		 sot.setNw(Integer.parseInt(nw));
	  } else if (in.matches("Soldiers: [0-9,]{1,} .*")) {
		 if (in.matches(".*gc.*"))
			return;
		 in = in.replace("Soldiers: ", "");
		 String soldiers = in.substring(0, in.indexOf(' '));
		 soldiers = soldiers.replace(",", "").trim();
		 sot.setSoldiers(Integer.parseInt(soldiers));
	  } else if (in.matches(CommonMethods.getOspecsRegex() + ": [0-9,]{1,}.*")) {
		 if (in.matches(".*gc.*"))
			return;
		 in = in.substring(in.indexOf(": ") + 1).trim();
		 if (in.indexOf(' ') != -1) {
			in = in.substring(0, in.indexOf(' '));
		 }
		 String ospecs = in.replace(",", "").trim();
		 sot.setOspecs(Integer.parseInt(ospecs));
	  } else if (in.matches(CommonMethods.getDspecsRegex() + ": [0-9,]{1,}.*")) {
		 if (in.matches(".*gc.*"))
			return;
		 in = in.substring(in.indexOf(' ')).trim();
		 if (in.indexOf(' ') != -1) {
			in = in.substring(0, in.indexOf(' '));
		 }
		 String dspecs = in.replace(",", "").trim();
		 sot.setDspecs(Integer.parseInt(dspecs));
	  } else if (in.matches(CommonMethods.getElitesRegex() + ": [0-9,]{1,}.*")) {
		 if (in.matches(".*gc.*"))
			return;
		 in = in.substring(in.indexOf(": ") + 1).trim();
		 if (in.indexOf(' ') != -1) {
			in = in.substring(0, in.indexOf(' '));
		 }
		 String elite = in.replace(",", "").trim();
		 sot.setElites(Integer.parseInt(elite));
	  } else if (in.matches("War-Horses: [0-9,]{1,20}.*")) {
		 if (in.matches(".*gc.*"))
			return;
		 in = in.replace("War-Horses: ", "");
		 if (in.indexOf(' ') != -1) {
			in = in.substring(0, in.indexOf(' '));
		 }
		 String horses = in.replace(",", "").trim();
		 sot.setHorses(Integer.parseInt(horses));
	  } else if (in.matches("Prisoners: [0-9,]{1,}.*")) {
		 if (in.matches(".*gc.*"))
			return;
		 in = in.replace("Prisoners: ", "");
		 if (in.indexOf(' ') != -1) {
			in = in.substring(0, in.indexOf(' '));
		 }
		 String prisoners = in.replace(",", "").trim();
		 sot.setPrisoners(Integer.parseInt(prisoners));
	  } else if (in.matches("Total Modified Offense: [0-9,]{1,}.*")) {
		 in = in.replace("Total Modified Offense: ", "");
		 if (in.indexOf(' ') != -1) {
			in = in.substring(0, in.indexOf(' '));
		 }
		 String off = in.replace(",", "").trim();
		 sot.setMo(Integer.parseInt(off));
	  } else if (in.matches("Total Modified Defense: [0-9,]{1,}.*")) {
		 in = in.replace("Total Modified Defense: ", "");
		 if (in.indexOf(' ') != -1) {
			in = in.substring(0, in.indexOf(' '));
		 }
		 String def = in.replace(",", "").trim();
		 sot.setMd(Integer.parseInt(def));
	  } else if (in.matches("Thieves: [0-9,]{1,}.*")) {
		 if (in.matches(".*gc.*"))
			return;
		 in = in.replace("Thieves: ", "");
		 if (in.indexOf(' ') != -1) {
			in = in.substring(0, in.indexOf(' '));
		 }
		 String thieves = in.replace(",", "").trim();
		 sot.setThieves(Integer.parseInt(thieves));
	  } else if (in.matches("Wizards: [0-9,]{1,}.*")) {
		 if (in.matches(".*gc.*"))
			return;
		 in = in.replace("Wizards: ", "");
		 if (in.indexOf(' ') != -1) {
			in = in.substring(0, in.indexOf(' '));
		 }
		 String wizards = in.replace(",", "").trim();
		 sot.setWizards(Integer.parseInt(wizards));
	  } else if ("Province was hit pretty heavily recently!".equals(in) || "Province was hit moderately recently!".equals(in)
			|| "Province was hit a little recently!".equals(in) || "Province was hit extremely badly recently!".equals(in)) {
		 String hit = in.replace("Province was ", "");
		 hit = hit.replace(" recently!", "");
		 hit = StringTools.capitalizeFirstLetters(hit);
		 sot.setHit(hit);
	  } else if (in.matches("A Ruby Dragon .*") || in.matches("An Emerald Dragon .*") || in.matches("A Sapphire Dragon .*")
			|| in.matches("A Gold Dragon .*")) {
		 String dragon = in.split(" ")[1];
		 sot.setDragon(dragon + " Dragon");
	  } else if (in.matches(".*The Plague has spread throughout the people.*")) {
		 sot.setPlague(true);
	  }
   }

   public boolean parseUnformattedSoT(final String input, final SoT sot) throws IntelParsingException {
	  int size = sot.getIntel().size();
	  final String persregex = CommonMethods.getPersonalitiesRegex();
	  final String titlesregex = CommonMethods.getTitlesRegex();
	  final String racesregex = CommonMethods.getRacesRegex(false);
	  String in = input;
	  if (in.matches(".*The Province of .*\\([0-9]{1,2}(:)[0-9]{1,2}\\) as of " + "(January|February|March|April|May|June|July) "
			+ "(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24) of YR[0-9]{1,2}"
			+ " \\(next tick: [0-9]{1,2} (minutes|minute|seconds|second)[ ]{0,1}\\)")) {
		 in = in.replaceAll(".*The Province of ", "");

		 final String prov = in.substring(0, in.indexOf('(')).trim();
		 final String kd = (in.substring(in.indexOf('('), in.indexOf(')')) + ")").trim();
		 String date = in.substring(in.indexOf("as of") + 6, in.indexOf("(next tick"));
		 date = date.replace(" of", ",");
		 UtopiaTime ut;
		 try {
			ut = new UtopiaTime(date.trim());
			Long time = ut.getTime();
			String intohour = in.substring(in.indexOf("(next tick: "));
			intohour = intohour.replaceAll("[^0-9]", "");
			if (in.contains("second")) {
			   time += (3600L - Integer.parseInt(intohour)) * 1000;
			} else {
			   time += (60L - Integer.parseInt(intohour)) * 60 * 1000;
			}
			sot.setName(prov);
			sot.setKdloc(kd);
			sot.setUpdated(new Date(time));
		 } catch (final UtoDateException e) {
			Logger.getLogger("Error").error("", e);
			throw new IntelParsingException();
		 }

	  } else if (in.matches("[0-9,]{1,}\t[0-9,]{1,}\t[0-9,]{1,}\t[0-9,]{1,}\t[0-9,]{1,}\t[0-9,]{1,}\t[0-9.]{1,}")) {
		 final String[] temp = in.split("\t");
		 sot.setNw(Integer.parseInt(temp[4].replace(",", "").trim()));
	  } else if (in.matches("Race[ ]{0,1}\t" + racesregex + "[ ]{0,1}\tSoldiers[ ]{0,1}\t[0-9,]{1,}")) {
		 final String[] temp = in.split("\t");
		 sot.setRace(temp[1].trim());
		 sot.setSoldiers(Integer.parseInt(temp[3].replace(",", "").trim()));
	  } else if (in.matches("Ruler[ ]{0,1}\t.*\t" + CommonMethods.getOspecsRegex() + "[ ]{0,1}\t[0-9,]{1,}")) {
		 final String[] temp = in.split("\t");

		 String pers = "";
		 String title = "";
		 String ruler = "";
		 if (temp[1].matches("The " + persregex + " " + titlesregex + " .*")) {
			temp[1] = temp[1].substring(4);
			pers = temp[1].substring(0, temp[1].indexOf(' ')).trim();
			title = temp[1].replace(pers, "").trim();
			ruler = title;
			title = title.substring(0, title.indexOf(' ')).trim();
			ruler = ruler.replace(title, "").trim();
		 } else if (temp[1].matches("The " + persregex + " .*")) {
			temp[1] = temp[1].substring(4);
			pers = temp[1].substring(0, temp[1].indexOf(' ')).trim();
			ruler = temp[1].replace(pers, "").trim();
			title = "Mr.";
		 } else if (temp[1].matches(titlesregex + " .* the " + persregex)) {
			title = temp[1].substring(0, temp[1].indexOf(' ')).trim();
			ruler = temp[1].replace(title, "").trim();
			pers = ruler;
			ruler = ruler.replaceAll("the " + persregex, "").trim();
			pers = pers.replace(ruler + " the ", "").trim();
		 }

		 pers = CommonMethods.getPersonalitiesMapping(pers);
		 title = CommonMethods.getTitleMapping(title);

		 sot.setTitle(title);
		 sot.setRulerName(ruler);
		 sot.setOspecs(Integer.parseInt(temp[3].replace(",", "").trim()));
		 sot.setPersonality(pers);
	  } else if (in.matches("Land[ ]{0,1}\t[0-9,]{1,}[ ]{0,1}\t" + CommonMethods.getDspecsRegex() + "[ ]{0,1}\t[0-9,]{1,}")) {
		 final String[] temp = in.split("\t");
		 temp[1] = temp[1].trim();
		 sot.setLand(Integer.parseInt(temp[1].replace(",", "")));
		 sot.setDspecs(Integer.parseInt(temp[3].replace(",", "").trim()));
	  } else if (in.matches("Peasants[ ]{0,1}\t[0-9,]{1,}[ ]{0,1}\t" + CommonMethods.getElitesRegex() + "[ ]{0,1}\t[0-9,]{1,}")) {
		 final String[] temp = in.split("\t");
		 sot.setPeasants(Integer.parseInt(temp[1].replace(",", "").trim()));
		 sot.setElites(Integer.parseInt(temp[3].replace(",", "").trim()));
	  } else if (in.matches("Building Eff.[ ]{0,1}\t[0-9.%]{1,}[ ]{0,1}\tThieves[ ]{0,1}\t[a-zA-Z0-9,]{1,}.*")) {
		 final String[] temp = in.split("\t");
		 temp[1] = temp[1].trim();
		 if (temp[3].matches("[0-9,]{1,}.*")) {
			temp[3] = temp[3].substring(0, temp[3].indexOf(' ')).trim();
		 } else {
			temp[3] = "-1";
			sot.setNw(0);
		 }
		 sot.setBe(temp[1]);
		 sot.setThieves(Integer.parseInt(temp[3].replace(",", "")));
	  } else if (in.matches("Money[ ]{0,1}\t[0-9,]{1,}[ ]{0,1}\tWizards[ ]{0,1}\t[a-zA-Z0-9,]{1,}.*")) {
		 final String[] temp = in.split("\t");
		 temp[1] = temp[1].trim();
		 if (temp[3].matches("[0-9,]{1,}.*")) {
			temp[3] = temp[3].substring(0, temp[3].indexOf(' ')).trim();
		 } else {
			temp[3] = "-1";
		 }
		 sot.setMoney(Integer.parseInt(temp[1].replace(",", "")));
		 sot.setWizards(Integer.parseInt(temp[3].replace(",", "")));
	  } else if (in.matches("Food[ ]{0,1}\t[0-9,]{1,}[ ]{0,1}\tWar Horses[ ]{0,1}\t[0-9,]{1,}")) {
		 final String[] temp = in.split("\t");
		 temp[1] = temp[1].trim();
		 sot.setFood(Integer.parseInt(temp[1].replace(",", "")));
		 sot.setHorses(Integer.parseInt(temp[3].replace(",", "").trim()));
	  } else if (in.matches("Runes[ ]{0,1}\t[0-9,]{1,}[ ]{0,1}\tPrisoners[ ]{0,1}\t[0-9,]{1,}")) {
		 final String[] temp = in.split("\t");
		 temp[1] = temp[1].trim();
		 sot.setRunes(Integer.parseInt(temp[1].replace(",", "")));
		 sot.setPrisoners(Integer.parseInt(temp[3].replace(",", "").trim()));
	  } else if (in.matches("Trade Balance[ ]{0,1}\t[-0-9,]{1,}[ ]{0,1}\tOff. Points[ ]{0,1}\t[0-9,]{1,}")) {
		 final String[] temp = in.split("\t");
		 temp[1] = temp[1].trim();
		 sot.setTradeBalance(Integer.parseInt(temp[1].replace(",", "")));
		 sot.setMo(Integer.parseInt(temp[3].replace(",", "").trim()));
	  } else if (in.matches(".*Def. Points[ ]{0,1}\t[0-9,]{1,}")) {
		 final String md = in.replaceAll("[^0-9]", "");
		 sot.setMd(Integer.parseInt(md));
	  }
	  return sot.getIntel().size() > size;
   }
}
